package cn.iocoder.yudao.module.dify.service.riskManagementReport;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.world.WordCountUtils;
import cn.iocoder.yudao.module.dify.api.vo.resp.DifyChatFlowUploadResponse;
import cn.iocoder.yudao.module.dify.api.vo.resp.ResponseData;
import cn.iocoder.yudao.module.dify.controller.admin.riskreportrecords.vo.RiskReportRecordsSaveReqVO;
import cn.iocoder.yudao.module.dify.dal.dataobject.riskreportrecords.RiskReportRecordsDO;
import cn.iocoder.yudao.module.dify.dal.mysql.riskreportrecords.RiskReportRecordsMapper;
import cn.iocoder.yudao.module.dify.service.riskreportrecords.RiskReportRecordsService;
import cn.iocoder.yudao.module.dify.util.MarkdownToWordUtil;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import org.apache.commons.io.IOUtils;
import javax.annotation.Resource;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils; // 导入 Apache Commons IO
/**
 * Dify风险管理报告  Service 接口
 *
 * @author 芋道源码
 */
@Slf4j
@Service
@Validated
@RequiredArgsConstructor
public class ChatFlowServiceImpl implements ChatFlowService {

    @Resource
    private FileApi fileApi;

    @Resource
    private RiskReportRecordsService riskReportRecordsService;

    @Resource
    private RiskReportRecordsMapper riskReportRecordsMapper;

    private final WebClient webClient;


    @Override
    public DifyChatFlowUploadResponse chatFlowUploadFile(String difyKey, MultipartFile file, Long userId) throws IOException {
        String apiUrl = "http://47.115.137.160/v1/files/upload";
        String user = userId.toString();
        RestTemplate restTemplate = new RestTemplate();
        WordCountUtils.WordCountResult wordCountResult = null;
        try (InputStream fileInputStream = file.getInputStream()) {
            wordCountResult = WordCountUtils.countWordsFromFileStream(fileInputStream, file.getOriginalFilename());
        } catch (IOException e) {
            System.err.println("统计文件字数时出错: " + e.getMessage());
        }
        try (InputStream uploadInputStream = file.getInputStream()) {

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
            headers.setBearerAuth(difyKey);
            MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
            byte[] fileBytes = IOUtils.toByteArray(uploadInputStream);
            ByteArrayResource resource = new ByteArrayResource(fileBytes) {
                @Override
                public String getFilename() {
                    return file.getOriginalFilename(); // 保留原始文件名
                }
            };

            body.add("file", resource);
            body.add("user", user);

            // 封装请求
            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);

            ResponseEntity<String> response = restTemplate.postForEntity(apiUrl, requestEntity, String.class);

            DifyChatFlowUploadResponse difyChatFlowUploadResponse = JSON.parseObject(response.getBody(), DifyChatFlowUploadResponse.class);
            // 添加一条任务
            RiskReportRecordsSaveReqVO riskReportRecordsSaveReqVO = new RiskReportRecordsSaveReqVO();
            riskReportRecordsSaveReqVO.setFileId(difyChatFlowUploadResponse.getId());
            riskReportRecordsSaveReqVO.setExtension(difyChatFlowUploadResponse.getExtension());
            riskReportRecordsSaveReqVO.setOriginalName(difyChatFlowUploadResponse.getName());
            riskReportRecordsSaveReqVO.setMimeType(difyChatFlowUploadResponse.getMime_type());
            riskReportRecordsSaveReqVO.setDifyResponse(difyChatFlowUploadResponse.toString());
            if (wordCountResult != null) {
                riskReportRecordsSaveReqVO.setCharacterCount(wordCountResult.characterCount());;
            }
            riskReportRecordsSaveReqVO.setProcessStatus(3); // 或者使用常量

            Long riskReportRecords = riskReportRecordsService.createRiskReportRecords(riskReportRecordsSaveReqVO);
            difyChatFlowUploadResponse.setRecordId(riskReportRecords);

            return difyChatFlowUploadResponse;
        } catch (IOException e) {
            // 处理上传过程中的IO错误
            System.err.println("上传文件时出错: " + e.getMessage());
            throw e; // 重新抛出异常
        }
    }

    @Override
    public Flux<ResponseData> getDifyRiskManagementReport(DifyChatFlowUploadResponse difyChatFlowUploadResponse, String query, Long userId, String difyApiKey) throws IOException {
        String apiUrl = "http://47.115.137.160/v1/chat-messages";
        StringBuffer stringBuffer = new StringBuffer("");
        //hutianhao.123
        // 构建请求体
        Map<String, Object> requestBody = new HashMap<>();
        Map<String, Object> inputsMap = new HashMap<>();

        requestBody.put("query", query);
        requestBody.put("response_mode", "streaming");
        requestBody.put("conversation_id", "");

        // 设置 user 字段
        requestBody.put("user", userId);

        // 构建 files 数组
        List<Map<String, Object>> files = new ArrayList<>();

        Map<String, Object> file = new HashMap<>();
        file.put("type", "document");
        file.put("transfer_method", "local_file");
        file.put("upload_file_id", difyChatFlowUploadResponse.getId());

        files.add(file);
        requestBody.put("files", files);
        inputsMap.put("fileList", files);
        inputsMap.put("query", query);
        requestBody.put("inputs", inputsMap);
        return webClient.post()
                .uri(apiUrl)
                .headers(httpHeaders -> {
                    httpHeaders.setContentType(MediaType.APPLICATION_JSON);
                    httpHeaders.setBearerAuth(difyApiKey);
                })
                .bodyValue(requestBody)
                .retrieve()
                .bodyToFlux(ResponseData.class)
                .timeout(Duration.ofMinutes(40)) // 设置最大等待时间
                .doOnNext(responseData -> log.info(responseData.getAnswer()))
                .onErrorResume(ex -> {
                    riskReportRecordsService.updateRiskReportStatus(difyChatFlowUploadResponse.getRecordId(), 2);
                    return Flux.error(ex);
                })
                ;
    }

    @Override
    public ResponseData getDifyRiskManagementReportBlocking(DifyChatFlowUploadResponse difyChatFlowUploadResponse, String query, Long userId, String difyApiKey) throws IOException {
        String apiUrl = "http://47.115.137.160/v1/chat-messages";
        // 构建请求体
        Map<String, Object> requestBody = new HashMap<>();
        Map<String, Object> inputsMap = new HashMap<>();

        requestBody.put("query", query);
        requestBody.put("response_mode", "blocking");
        requestBody.put("conversation_id", "");

        // 设置 user 字段
        requestBody.put("user", userId);

        // 构建 files 数组
        List<Map<String, Object>> files = new ArrayList<>();

        Map<String, Object> file = new HashMap<>();
        file.put("type", "document");
        file.put("transfer_method", "local_file");
        file.put("upload_file_id", difyChatFlowUploadResponse.getId());

        files.add(file);
        requestBody.put("files", files);
        inputsMap.put("fileList", files);
        inputsMap.put("query", query);
        requestBody.put("inputs", inputsMap);
        return webClient.post()
                .uri(apiUrl)
                .headers(httpHeaders -> {
                    httpHeaders.setContentType(MediaType.APPLICATION_JSON);
                    httpHeaders.setBearerAuth(difyApiKey);
                })
                .bodyValue(requestBody)
                .retrieve()
                .bodyToMono(ResponseData.class).timeout(Duration.ofMinutes(40)) // 改用 bodyToMono
                .block(); // 同步阻塞等待结果
    }

    @Override
    public Boolean executeGenerationRiskManagementReport(DifyChatFlowUploadResponse difyChatFlowUploadResponse, String query, Long userId, String difyApiKey) throws Exception {
        //请求dify接口
        Flux<ResponseData> responseDataFlux = getDifyRiskManagementReport(difyChatFlowUploadResponse, query, userId, difyApiKey);
        //解析dify接口返回数据
        StringBuilder markdownString = MarkdownToWordUtil.writeMarkdownString(responseDataFlux);
        String filePath = "";
        if (FileUtil.isWindows()) {
            filePath = "D:\\difyWord\\" + difyChatFlowUploadResponse.getRecordId() + difyChatFlowUploadResponse.getName();
        } else {
            filePath = "/opt/app/difyWord/" + difyChatFlowUploadResponse.getRecordId() + difyChatFlowUploadResponse.getName();
        }
        if (markdownString.length() > 500) {
            MarkdownToWordUtil.markdownStringToWordFilePoiTl(markdownString.toString(), filePath);
            BufferedInputStream inputStream = FileUtil.getInputStream(filePath);
            //dify数据保存 用于观察数据 后续可以注释掉
            String markdownFileUrl = fileApi.createFile(difyChatFlowUploadResponse.getName(), FileNameUtil.mainName(difyChatFlowUploadResponse.getName()) + "dify返回.txt", StrUtil.utf8Bytes(markdownString));
            String file = fileApi.createFile(difyChatFlowUploadResponse.getName(), FileNameUtil.mainName(difyChatFlowUploadResponse.getName()) + "风险管理报告.docx", IoUtil.readBytes(inputStream));
            RiskReportRecordsDO riskReportRecords = riskReportRecordsService.getRiskReportRecords(difyChatFlowUploadResponse.getRecordId());
            riskReportRecords.setMinioUrl(file);
            riskReportRecords.setDifyDownloadUrl(markdownFileUrl);
            riskReportRecords.setProcessStatus(1);
            riskReportRecords.setUpdateTime(LocalDateTime.now());
            riskReportRecordsMapper.updateById(riskReportRecords);
        } else {
            riskReportRecordsService.updateRiskReportStatus(difyChatFlowUploadResponse.getRecordId(), 2);
        }
        return true;

    }

    @Override
    public Boolean riskManagementReportPerformTasks(Long id, Long userId, String difyApiKey) throws Exception {

        RiskReportRecordsDO riskReportRecords = riskReportRecordsService.getRiskReportRecords(id);
        DifyChatFlowUploadResponse difyChatFlowUploadResponse = new DifyChatFlowUploadResponse();
        difyChatFlowUploadResponse.setId(riskReportRecords.getFileId());
        difyChatFlowUploadResponse.setName(riskReportRecords.getOriginalName());
        difyChatFlowUploadResponse.setRecordId(id);
        riskReportRecords.setProcessStatus(0);
        riskReportRecordsMapper.updateById(riskReportRecords);
        return executeGenerationRiskManagementReport(difyChatFlowUploadResponse, "1", userId, difyApiKey);
    }

    @Override
    public Boolean executeGenerationRiskManagementReportBlocking(DifyChatFlowUploadResponse difyChatFlowUploadResponse, String query, Long userId, String difyApiKey) throws Exception {
        //请求dify接口
        ResponseData difyRiskManagementReportBlocking = getDifyRiskManagementReportBlocking(difyChatFlowUploadResponse, query, userId, difyApiKey);
        String answer = difyRiskManagementReportBlocking.getAnswer();
        String filePath = "";
        if (FileUtil.isWindows()) {
            filePath = "D:\\difyWord\\" + difyChatFlowUploadResponse.getRecordId() + difyChatFlowUploadResponse.getName();
        } else {
            filePath = "/app2/difyWord/" + difyChatFlowUploadResponse.getRecordId() + difyChatFlowUploadResponse.getName();
        }
        if (StrUtil.isNotEmpty(answer) && answer.length() > 500) {
            MarkdownToWordUtil.markdownStringToWordFilePoiTl(answer, filePath);
            BufferedInputStream inputStream = FileUtil.getInputStream(filePath);
            String file = fileApi.createFile(difyChatFlowUploadResponse.getName(), "风险报告:" + difyChatFlowUploadResponse.getName(), IoUtil.readBytes(inputStream));
            RiskReportRecordsDO riskReportRecords = riskReportRecordsService.getRiskReportRecords(difyChatFlowUploadResponse.getRecordId());
            riskReportRecords.setMinioUrl(file);
            riskReportRecords.setProcessStatus(1);
            riskReportRecords.setUpdateTime(LocalDateTime.now());
            riskReportRecordsMapper.updateById(riskReportRecords);
        }
        return true;
    }

    @Override
    public Boolean riskManagementReportRetry(Long id, Long userId, String difyApiKey) throws Exception {
        RiskReportRecordsDO riskReportRecords = riskReportRecordsService.getRiskReportRecords(id);
        riskReportRecords.setRetryCount(riskReportRecords.getRetryCount() + 1);
        riskReportRecordsMapper.updateById(riskReportRecords);
        DifyChatFlowUploadResponse difyChatFlowUploadResponse = new DifyChatFlowUploadResponse();
        difyChatFlowUploadResponse.setId(riskReportRecords.getFileId());
        difyChatFlowUploadResponse.setName(riskReportRecords.getOriginalName());
        difyChatFlowUploadResponse.setRecordId(id);
        executeGenerationRiskManagementReport(difyChatFlowUploadResponse, "1", userId, difyApiKey);
        return true;
    }


}
